package com.jahentao.patentQuery.web.controller;

import com.aliyun.mns.common.ServiceException;
import com.jahentao.patentQuery.constant.Constants;
import com.jahentao.patentQuery.constant.EhCacheKeys;
import com.jahentao.patentQuery.exception.CaptchaErrorException;
import com.jahentao.patentQuery.mapper.SessionMapper;
import com.jahentao.patentQuery.model.Session;
import com.jahentao.patentQuery.model.SessionExample;
import com.jahentao.patentQuery.model.User;
import com.jahentao.patentQuery.model.bean.MessageCode;
import com.jahentao.patentQuery.model.bean.ResultBean;
import com.jahentao.patentQuery.service.RegisterValidateService;
import com.jahentao.patentQuery.service.SessionService;
import com.jahentao.patentQuery.service.UserLoginService;
import com.jahentao.patentQuery.service.UserService;
import com.jahentao.patentQuery.util.IpUtil;
import com.jahentao.patentQuery.web.shiro.jcaptcha.JCaptcha;
import com.jahentao.patentQuery.web.shiro.spring.SpringCacheManagerWrapper;
import com.qq.connect.QQConnectException;
import com.qq.connect.api.OpenID;
import com.qq.connect.api.qzone.UserInfo;
import com.qq.connect.javabeans.AccessToken;
import com.qq.connect.javabeans.qzone.UserInfoBean;
import com.qq.connect.oauth.Oauth;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.security.auth.Subject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 第三方登录控制器
 * <p>目前支持QQ登录</p>
 * @author jahentao
 * @date 2018/5/26
 * @since 1.0
 */
@Controller
public class ThirdPartyLoginController extends BaseController {

    @Autowired
    private UserService userService;
    @Autowired
    private Oauth qqOauth;
    @Autowired
    private SessionService sessionService;


    @Value("app_ID")
    private String appId;
    @Value("app_KEY")
    private String appKey;

    /**
     * QQ第三方登录
     */
    @RequestMapping(value = "qqLogin")
    public void  qqLogin(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("text/html;charset=utf-8");
        try {
            // 生成引导用户前往确认授权的页面地址AuthorizeURL
            response.sendRedirect(qqOauth.getAuthorizeURL(request));
        } catch (QQConnectException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 用于QQ登录的回调，进行用户信息的保存操作等
     * <p>网站回调域 : http://zhiwanqian.com/patentQuery/qqauth</p>
     */
    @RequestMapping(value = "qqauth", method = RequestMethod.GET)
    protected void qqauth(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html; charset=utf-8");

//        PrintWriter out = response.getWriter();
        String code = request.getParameter("code");
        String state = request.getParameter("state");
//        System.out.println("code : " + code + ", state : " + state);

        String sessionId = SecurityUtils.getSubject().getSession().getId().toString();
        String openID = null;

        try {
            AccessToken token = (new Oauth()).getAccessTokenByRequest(request);
            logger.debug("QQ 登录 token: {}", token);

            String accessToken = token.getAccessToken();

            // 利用获取到的accessToken 去获取当前用的openid
            OpenID openIDObj = new OpenID(accessToken);
            openID = openIDObj.getUserOpenID();
            request.getSession().setAttribute("openId", openID);

            User user = new User();
            Session session = new Session();;

            // 查看用户是否已经存在
            SessionExample sessionExample = new SessionExample();
            sessionExample.createCriteria().andOpenIdEqualTo(openID);
            List<Session> sessions = sessionService.selectByExample(sessionExample);
            if (sessions == null || sessions.size() == 0) {
                // session不存在
                // 即用户第一次QQ登录

                // 利用获取到的accessToken,openid 去获取用户在Qzone的昵称等信息
                UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);
                UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
                // 昵称
                user.setUsername(userInfoBean.getNickname());
                // 性别
                user.setGender("男".equals(userInfoBean.getGender()));
                // 头像 url
                user.setAvatar(userInfoBean.getAvatar().getAvatarURL50());

                // 保存 user
                // QQ登录的为“游客”
                user.setUtype(String.valueOf(User.UserTypeEnum.VISITOR));
                // 未完善信息，不合法
                user.setValidated((byte) 0);
                user.setLocked((byte) 0);

                // 保存新用户之前，查看用户是否已经存在
                userService.save(user);

                if (token.getAccessToken() != null) {
                    accessToken = token.getAccessToken();
                    long tokenExpireIn = token.getExpireIn();
                    session.setOpenId(openID);
                    session.setAccessToken(accessToken);
                    session.setGmtCreate(new Date());
                    session.setGmtModified(new Date());
                    session.setValidated(true);
//                session.setSession(sessionId); // 反正会过期，存储并没有意义。shiro的会话缓存已经整合入EhCache
                    session.setExpireIn(token.getExpireIn());
                    session.setUserId(user.getId());

                    sessionService.save(session);
                }
            } else {
                // session 存在，即用户也存在

            }

        } catch (QQConnectException e) {
            // TODO 提醒用户登录失败，再试一次
            logger.info("会话{} QQ登录失败", sessionId);
            e.printStackTrace();
        }
        response.sendRedirect("index.html?openId="+openID);
    }

    /**
     * 未认证，没有权限
     * @param request
     * @param response
     */
    @RequestMapping(value="unauthorized") //, method=RequestMethod.POST
    public void unauthorized(HttpServletRequest request, HttpServletResponse response) {
        String session = SecurityUtils.getSubject().getSession().getId().toString();
        logger.info("会话{} 没有权限", session);
    }

}
